package cn.sylinx.hbatis.ext.ifblock;

import java.util.List;
import java.util.Stack;

import cn.sylinx.hbatis.ext.parse.TokenHandler;
import cn.sylinx.hbatis.kit.Tuple;

public class IfEndBlockParserImpl implements IfEndBlockParser {

	private char keyword = '#';
	private Stack<Node> stack = new Stack<Node>();

	private StringBuilder sb = new StringBuilder();

	private IfEndBlock ifEndBlockForResult = null;
	private TokenHandler handler;

	public IfEndBlockParserImpl(TokenHandler handler) {
		this.handler = handler;
	}

	public String parse(String statement) {

		stack.clear();
		sb.setLength(0);
		ifEndBlockForResult = null;

		IfEndBlock ifEndBlock = parseIfEndBlock(statement);
		return parseContent(statement, ifEndBlock);
	}

	private IfEndBlock parseIfEndBlock(String statement) {

		int len = statement.length();
		boolean meetKeyWord = false;
		String node = null;

		for (int i = 0; i < len; ++i) {

			char c = statement.charAt(i);
			if (keyword == c) {
				meetKeyWord = true;
				sb.append(c);
				continue;
			}

			if (meetKeyWord) {
				sb.append(c);
				node = sb.toString();

				if(node.startsWith(Tags.KW_FUNC)) {
					// 遇到的是函数
					sb.setLength(0);
					meetKeyWord = false;

				} else if (node.startsWith(Tags.VAR_PREFIX)) {
					// 遇到的是变量前缀
					sb.setLength(0);
					meetKeyWord = false;

				} else if (node.equals(Tags.KW_IF)) {
					// 匹配到IF

					withIf(statement, i);
					sb.setLength(0);
					meetKeyWord = false;

				} else if (node.equals(Tags.KW_ELSIF)) {
					// 匹配到ELSIF

					withElsif(statement, i);
					sb.setLength(0);
					meetKeyWord = false;

				} else if (node.equals(Tags.KW_ELSE)) {
					// 匹配到ELSE

					withElse(statement, i);
					sb.setLength(0);
					meetKeyWord = false;

				} else if (node.equals(Tags.KW_END)) {
					// 匹配到END

					withEnd(statement, i);
					sb.setLength(0);
					meetKeyWord = false;
				}
			}
		}

		return stack.empty() ? ifEndBlockForResult : null;
	}

	/**
	 * 处理end
	 * 
	 * @param statement
	 * @param index
	 */
	private void withEnd(String statement, int index) {

		Node node = stack.peek();
		if (node == null) {
			throw new RuntimeException("end prenode not exist.");
		}

		END end = new END();
		end.setIndex(index);
		end.setNextIndex(index + 1);

		// 如果是IF实例
		if (node instanceof IF) {
			IF ifnode = (IF) node;
			ifnode.setFollowNode(end);
			String contentPattern = statement.substring(ifnode.getNextIndex(),
					end.getIndex() - Tags.KW_END.length() + 1);
			ifnode.setContentPattern(contentPattern);
			end.setPreNode(ifnode);

		} else if (node instanceof ELSIF) {
			// 如果是ELSIF实例
			ELSIF preElsif = (ELSIF) node;
			preElsif.setFollowNode(end);
			String contentPattern = statement.substring(preElsif.getNextIndex(),
					end.getIndex() - Tags.KW_END.length() + 1);
			preElsif.setContentPattern(contentPattern);
			end.setPreNode(preElsif);

		} else if (node instanceof ELSE) {
			// 如果是ELSE实例

			ELSE preElse = (ELSE) node;
			String contentPattern = statement.substring(preElse.getNextIndex(),
					end.getIndex() - Tags.KW_END.length() + 1);
			preElse.setContentPattern(contentPattern);
			end.setPreNode(preElse);
			preElse.setEndNode(end);
		}

		// 此处需要出队列
		outStack(statement, end);
	}

	private void outStack(String statement, END end) {

		IfEndBlock block = new IfEndBlock();
		block.setEndNode(end);

		Node a = null;

		do {
			a = stack.pop();

			if (a instanceof IF) {
				block.setIfNode((IF) a);
			}

			if (a instanceof ELSIF) {
				block.addElsifNode((ELSIF) a);
			}

			if (a instanceof ELSE) {
				block.setElseNode((ELSE) a);
			}

		} while (!(a instanceof IF));

		if (stack.empty()) {

			// 为空则遍历完毕，此处为获取最终结果
			this.ifEndBlockForResult = block;

		} else {

			Node node = stack.peek();

			// 如果是IF实例
			if (node instanceof IF) {
				IF ifnode = (IF) node;
				ifnode.addIfEndBlock(block);

			} else if (node instanceof ELSIF) {
				// 如果是ELSIF实例
				ELSIF preElsif = (ELSIF) node;
				preElsif.addIfEndBlock(block);

			} else if (node instanceof ELSE) {
				// 如果是ELSE实例

				ELSE preElse = (ELSE) node;
				preElse.addIfEndBlock(block);
			}

		}
	}

	private String parseFollowNodeContent(String statement, FollowNode fn) {

		if (fn instanceof END) {
			// #END 说明条件不符合
			return "";

		} else if (fn instanceof ELSIF) {
			// #ELSIF 判断
			ELSIF elsifTmp = (ELSIF) fn;

			if (handler.condition(elsifTmp.getCondition())) {

				List<IfEndBlock> list = elsifTmp.getIfEndBlockList();

				if (list.isEmpty()) {
					// 没有内部ifendblock
					return elsifTmp.getContentPattern();

				} else {

					int index = elsifTmp.getNextIndex();
					Tuple[] indexList = new Tuple[list.size()];
					String[] contentList = new String[list.size()];

					for (int i = 0; i < list.size(); ++i) {

						IfEndBlock iebBlcok = list.get(i);
						// 保存起始结束索引
						indexList[i] = Tuple.apply(
								iebBlcok.getIfNode().getIndex() + 1 - iebBlcok.getIfNode().getNodeName().length(),
								iebBlcok.getEndNode().getNextIndex());
						contentList[i] = parseContent(statement, iebBlcok);
					}

					StringBuilder sb = new StringBuilder();
					for (int i = 0; i < indexList.length; ++i) {

						if (i == 0) {

							Tuple t = indexList[i];
							int endIndex = t.getObject(0);
							sb.append(statement.substring(index, endIndex)).append(contentList[i]);

						} else {
							Tuple t = indexList[i];
							Tuple t1 = indexList[i - 1];
							int beginIndex = t1.getObject(1);
							int endIndex = t.getObject(0);
							sb.append(statement.substring(beginIndex, endIndex)).append(contentList[i]);
						}

						if (i == indexList.length - 1) {
							// 最后一条
							Tuple t = indexList[indexList.length - 1];
							int beginIndex = t.getObject(1);
							int endIndex = elsifTmp.getFollowNode().getIndex() + 1
									- elsifTmp.getFollowNode().getNodeName().length();
							sb.append(statement.substring(beginIndex, endIndex));
						}

					}

					return sb.toString();
				}

			} else {

				return parseFollowNodeContent(statement, ((ELSIF) fn).getFollowNode());
			}

		} else if (fn instanceof ELSE) {
			// #ELSE块

			ELSE elseTmp = (ELSE) fn;
			List<IfEndBlock> list = elseTmp.getIfEndBlockList();

			if (list.isEmpty()) {
				// 没有内部ifendblock
				return elseTmp.getContentPattern();

			} else {

				int index = elseTmp.getNextIndex();
				Tuple[] indexList = new Tuple[list.size()];
				String[] contentList = new String[list.size()];

				for (int i = 0; i < list.size(); ++i) {

					IfEndBlock iebBlcok = list.get(i);
					// 保存起始结束索引
					indexList[i] = Tuple.apply(
							iebBlcok.getIfNode().getIndex() + 1 - iebBlcok.getIfNode().getNodeName().length(),
							iebBlcok.getEndNode().getNextIndex());
					contentList[i] = parseContent(statement, iebBlcok);
				}

				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < indexList.length; ++i) {

					if (i == 0) {

						Tuple t = indexList[i];
						int endIndex = t.getObject(0);
						sb.append(statement.substring(index, endIndex)).append(contentList[i]);

					} else {
						Tuple t = indexList[i];
						Tuple t1 = indexList[i - 1];
						int beginIndex = t1.getObject(1);
						int endIndex = t.getObject(0);
						sb.append(statement.substring(beginIndex, endIndex)).append(contentList[i]);
					}

					if (i == indexList.length - 1) {
						// 最后一条
						Tuple t = indexList[indexList.length - 1];
						int beginIndex = t.getObject(1);
						int endIndex = elseTmp.getEndNode().getIndex() + 1
								- elseTmp.getEndNode().getNodeName().length();
						sb.append(statement.substring(beginIndex, endIndex));
					}

				}

				return sb.toString();

			}

		}

		// 不存在的FollowNode
		return "";
	}

	private String parseContent(String statement, IfEndBlock block) {

		if (block == null) {
			return "";
		}

		// #IF 内容
		IF ifnode = block.getIfNode();
		List<IfEndBlock> list = ifnode.getIfEndBlockList();
		String condition = ifnode.getCondition();
		if (handler.condition(condition)) {

			if (list.isEmpty()) {

				// #IF 符合条件
				return ifnode.getContentPattern();

			} else {

				// 不为空重新遍历

				int index = ifnode.getNextIndex();
				Tuple[] indexList = new Tuple[list.size()];
				String[] contentList = new String[list.size()];

				for (int i = 0; i < list.size(); ++i) {

					IfEndBlock iebBlcok = list.get(i);
					// 保存起始结束索引
					indexList[i] = Tuple.apply(
							iebBlcok.getIfNode().getIndex() + 1 - iebBlcok.getIfNode().getNodeName().length(),
							iebBlcok.getEndNode().getNextIndex());
					contentList[i] = parseContent(statement, iebBlcok);
				}

				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < indexList.length; ++i) {

					if (i == 0) {

						Tuple t = indexList[i];
						int endIndex = t.getObject(0);
						sb.append(statement.substring(index, endIndex)).append(contentList[i]);

					} else {
						Tuple t = indexList[i];
						Tuple t1 = indexList[i - 1];
						int beginIndex = t1.getObject(1);
						int endIndex = t.getObject(0);
						sb.append(statement.substring(beginIndex, endIndex)).append(contentList[i]);
					}

					if (i == indexList.length - 1) {
						// 最后一条
						Tuple t = indexList[indexList.length - 1];
						int beginIndex = t.getObject(1);
						int endIndex = ifnode.getFollowNode().getIndex() + 1
								- ifnode.getFollowNode().getNodeName().length();
						sb.append(statement.substring(beginIndex, endIndex));
					}

				}

				return sb.toString();
			}

		} else {

			// 查找#ELSIF 或者 #ELSE 或者 #END
			FollowNode fn = ifnode.getFollowNode();
			return parseFollowNodeContent(statement, fn);
		}

	}

	/**
	 * 处理else
	 * 
	 * @param statement
	 * @param index
	 */
	private void withElse(String statement, int index) {

		Node node = stack.peek();
		if (node == null) {
			throw new RuntimeException("else prenode not exist.");
		}

		ELSE elseNode = new ELSE();
		elseNode.setIndex(index);
		elseNode.setNextIndex(index + 1);

		// 如果是IF实例
		if (node instanceof IF) {
			IF ifnode = (IF) node;
			ifnode.setFollowNode(elseNode);
			elseNode.setPreNode(ifnode);
			String contentPattern = statement.substring(ifnode.getNextIndex(),
					elseNode.getIndex() - Tags.KW_ELSE.length() + 1);
			ifnode.setContentPattern(contentPattern);

		} else if (node instanceof ELSIF) {
			// 如果是ELSIF实例
			ELSIF preElsif = (ELSIF) node;
			preElsif.setFollowNode(elseNode);
			elseNode.setPreNode(preElsif);
			String contentPattern = statement.substring(preElsif.getNextIndex(),
					elseNode.getIndex() - Tags.KW_ELSE.length() + 1);
			preElsif.setContentPattern(contentPattern);
		}

		stack.push(elseNode);
	}

	/**
	 * 处理elsif
	 * 
	 * @param statement
	 * @param index
	 */
	private void withElsif(String statement, int index) {

		Node node = stack.peek();
		if (node == null) {
			throw new RuntimeException("elsif prenode not exist.");
		}

		String left = statement.substring(index + 2);
		int tce = left.indexOf(Tags.TOKEN_CON_END);
		String condition = left.substring(0, tce);

		ELSIF elsifNode = new ELSIF();
		elsifNode.setCondition(condition);
		elsifNode.setIndex(index);
		elsifNode.setNextIndex(index + 2 + tce + 1);

		// 如果是IF实例
		if (node instanceof IF) {
			IF ifnode = (IF) node;
			ifnode.setFollowNode(elsifNode);
			elsifNode.setPreNode(ifnode);
			String contentPattern = statement.substring(ifnode.getNextIndex(),
					elsifNode.getIndex() - Tags.KW_ELSIF.length() + 1);
			ifnode.setContentPattern(contentPattern);

		} else if (node instanceof ELSIF) {
			// 如果是ELSIF实例
			ELSIF preElsif = (ELSIF) node;
			preElsif.setFollowNode(elsifNode);
			elsifNode.setPreNode(preElsif);
			String contentPattern = statement.substring(preElsif.getNextIndex(),
					elsifNode.getIndex() - Tags.KW_ELSIF.length() + 1);
			preElsif.setContentPattern(contentPattern);
		}

		stack.add(elsifNode);
	}

	/**
	 * 处理 IF
	 * 
	 * @param statement
	 * @param index
	 */
	private void withIf(String statement, int index) {

		String left = statement.substring(index + 2);
		int tce = left.indexOf(Tags.TOKEN_CON_END);
		String condition = left.substring(0, tce);

		IF ifnode = new IF();
		ifnode.setCondition(condition);
		ifnode.setIndex(index);
		ifnode.setNextIndex(index + 2 + tce + 1);
		stack.add(ifnode);
	}

}
